#ifndef GANTRY_AGENT_H_
#define GANTRY_AGENT_H_


#include <string>
#include <queue>
#include <vector>
#include "Agent.h"
#include "Gantry.h"
#include "Lock.h"
#include "FeederAgent.h"
#include "Structs.h"
#include "Enums.h"
#include "GUIGantry.h"
#include "Sema.h"

class FeederAgent;
class GUIGantry;

class GantryAgent : public Agent,public Gantry {

private:
	Feeder* feeder1;
	Feeder* feeder2;
	Feeder* feeder3;
	Feeder* feeder4;
	//Sema waitingStatus;
	//std::queue<FeederOrder>* completedRecipes;
	//std::list<FeederOrder>* waitingRecipes;
	//std::list<FeederOrder>* newRecipes;
	//std::list<int> purgeList;
	//std::list<int> feederFree;
	std::vector<PartType> binLocations;
	GUIGantry* guiGantry;

	enum GantryStatus{NEW,CHECKSTATUS=500,BIN=502,GUIBIN=503,MOVE=504,ONWAYFEEDER=505,TELLFEEDER=506,IDLE=507};
	struct GantryUnit{ FeederOrder order; 
	GantryStatus state;
	GantryUnit::GantryUnit(FeederOrder o,GantryStatus s){order=o;state=s;}
	};
	std::queue<GantryUnit>* gantryOrders;
	Lock gantryOrdersLock;

	class AwakeThread : public Thread {
	public:
		AwakeThread() {}
		AwakeThread(GantryAgent* robot) {
			myAgent = robot;
		}
	protected:
		virtual void run() {
			sleep(30);
			if(myAgent->isWaiting)
				myAgent->feederJammed();
		}


	private:
		GantryAgent* myAgent;
	};

	AwakeThread timer;
	bool purgeFeeder;
	bool explode;

public:
	//constructor
	GantryAgent(std::string myname);

	//mesages
	void msgExplode();
	void msgPleaseGetParts(PartRecipe newPart, Feeder* newFeeder);
	void msgGUIHalfDoneMoving(int num);
	void msgGUIDoneMoving();
	void msgFeederStatus(Feeder* feeder,bool busy);
	void msgPurgeFeeder();
	

	//scheduler
	virtual bool pickAndExecuteAnAction();

	//Actions:
	void moveToBin(FeederOrder newOrder);
	void moveGantryToFeeder(FeederOrder newOrder);
	void checkStatusOfFeeder(FeederOrder newOrder);
	void gantryDoneMovingSendParts(FeederOrder newOrder);
	//GUIGantry* getGUI();
	virtual std::string toString() const;

	void setFeeder1(Feeder* feed1);
	void setFeeder2(Feeder* feed2);
	void setFeeder3(Feeder* feed3);
	void setFeeder4(Feeder* feed4);
	void setGuiGantry(GUIGantry* hey);

	GUIGantry* getGUI();
	Feeder* getFeeder1();
	Feeder* getFeeder2();
	Feeder* getFeeder3();
	Feeder* getFeeder4();
	void setStartBins(std::vector<PartType> parts);
	void setBin(PartType part,int bin);
	void goIdle();


	void feederJammed();

	bool isWaiting;
	int waitingFeeder;

	
	void handleBreak();
	void handleFix();

	//other stuff
protected:
	

};

#endif